package com.yaodian100.ec.shopping.entity;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import com.yaodian100.core.common.entity.BaseEntity;
import com.yaodian100.ec.campaign.entity.CampaignProduct;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.entity.Specification;
import com.yaodian100.ec.shelf.entity.Shelf;
import com.yaodian100.ec.shelf.entity.ShelfTuangou;

@Entity
@Table(name = "EC_CART_ORDER_PRODUCT")
public class CartOrderProduct extends BaseEntity {

	private static final long serialVersionUID = 5011439253875700516L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO, generator = "seq_ec_cart_order_prod")
	@SequenceGenerator(name = "seq_ec_cart_order_prod", sequenceName = "seq_ec_cart_order_prod")
	@Column(name = "cart_order_prod_id")
	private Long cartOrderProdId;

	@Column(name = "cart_id", length = 50, insertable = false, updatable = false)
	private String cartId;
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "cart_id", nullable = false)
	private CartOrders cart;

	@Column(name = "prod_id", length = 10, nullable = false)
	private String prodId;

	@Column(name = "prod_spec_id", length = 10, nullable = false)
	private String prodSpecId;

	@Column(name = "prod_name", length = 500, nullable = false)
	private String prodName;

	@Column(name = "prod_spec_name", length = 100)
	private String prodSpecName;

	@Column(name = "prod_tp", length = 5, nullable = false)
	private String prodTp;

	@Column(name = "logistic_tp", length = 5)
	private String logisticTp = " ";

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "logistic_send_dt")
	private Date logisticSendDt;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "logistic_final_dt")
	private Date logisticFinalDt;

	@Column(name = "logistic_st", length = 5)
	private String logisticSt = " ";

	@Column(name = "logistic_no", length = 20)
	private String logisticNo = " ";

	@Column(name = "logistic_company", length = 15)
	private String logisticCompany = " ";

	/** ecCost, product.productCose 報表需要 */
	@Column(name = "ec_cost", nullable = false, columnDefinition = "numeric(10,2)")
	private BigDecimal ecCost = BigDecimal.ZERO;

	@Column(name = "epr_cost", nullable = false, columnDefinition = "numeric(10,2)")
	private BigDecimal erpCost = BigDecimal.ZERO;

	/** unitPrice, 主商品單位售價, 不含 addOn */
	@Column(name = "unit_price", nullable = false, columnDefinition = "numeric(10,2)")
	private BigDecimal unitPrice = BigDecimal.ZERO;

	/** qty, 主商品的購買量, for 退換貨 */
	@Column(name = "qty", nullable = false)
	private int qty = 0;

	/** totalPrice, detail 售價的總計, 包含 addOn */
	@Column(name = "total_price", nullable = false, columnDefinition = "numeric(10,2)")
	private BigDecimal totalPrice = BigDecimal.ZERO.setScale(1);

	// /** amount, 主商品售價, 不含 addOn */
	// @Column(name = "amount", nullable = false, columnDefinition = "numeric(10,2)")
	// private BigDecimal amount = BigDecimal.ZERO;

	/** discount, 活動折扣金額, (滿額購直接維護售價, 不包含於此), 不存於資料庫, 計算結果 */
	@Transient
	private BigDecimal discount = BigDecimal.ZERO.setScale(1);

	@Column(name = "category_path", length = 80, nullable = false)
	private String categoryPath;

	@Column(name = "pm_id", length = 20)
	private String pmId;

	@Column(name = "pm_group", length = 20)
	private String pmGroup;

	@Column(name = "is_campaign")
	private boolean isCampaign;

	@Column(name = "is_return")
	private boolean isReturn;

	@Column(name = "is_change")
	private boolean isChange;

	@Column(name = "campaign_id", length = 40)
	private String campaignId = " ";

	@Column(name = "campaign_name", length = 100)
	private String campaignName = " ";

	@OneToMany(targetEntity = CartOrderProductDetail.class, mappedBy = "orderProduct")
	@Cascade( { CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN })
	@OnDelete(action = OnDeleteAction.CASCADE)
	@LazyCollection(LazyCollectionOption.FALSE)
	private List<CartOrderProductDetail> details;

	@Column(name = "prod_seq", nullable = false, columnDefinition = "numeric(5)")
	private int prodSeq = 0;

	@Transient
	private List<ApplyCampaign> applyCampaign;
	@Transient
	private String isScm;
	@Transient
	private String supplierId;

	/** default constructor */
	public CartOrderProduct() {
		super();
	}

	public CartOrderProduct(Product prod, Specification spec, Shelf shelf, String categoryPath, int qty,
			CampaignProduct cp) {
		super();
		this.prodId = prod.getProductId();
		this.prodName = prod.getProductName();
		this.pmId = prod.getPmID();
		this.pmGroup = prod.getOrganizationPath();
		this.ecCost = prod.getProductCost();

		this.prodSpecId = spec.getSpecificationId().toString();
		this.prodSpecName = spec.getSpecificationName();
		this.categoryPath = categoryPath;

		this.qty = qty;
		this.unitPrice = shelf.getShelfPrice();
		if (cp != null) {
			this.unitPrice = cp.getPrice();
			this.prodTp = "5";
			this.campaignId = cp.getUuid();
		} else {
			this.prodTp = String.valueOf(prod.getProductType());
		}
		if (StringUtils.isNotBlank(prod.getIsScm())) {
			this.isScm = prod.getIsScm();
		}
		if (StringUtils.isNotBlank(prod.getSupplierId())) {
			this.supplierId = prod.getSupplierId();
		}
		// this.totalPrice = this.unitPrice.multiply(BigDecimal.valueOf(this.qty));
		// this.amount = this.totalPrice;
	}

	public CartOrderProduct(Product prod, Specification spec, ShelfTuangou shelfTuangou, String categoryPath, int qty) {
		this.prodId = prod.getProductId();
		this.prodName = prod.getProductName();
		this.pmId = prod.getPmID();
		this.pmGroup = prod.getOrganizationPath();
		this.ecCost = prod.getProductCost();
		this.prodSpecId = spec.getSpecificationId().toString();
		this.prodSpecName = spec.getSpecificationName();
		this.categoryPath = categoryPath;

		this.qty = qty;
		this.unitPrice = shelfTuangou.getPrice();
		this.prodTp = String.valueOf(prod.getProductType());
		if (StringUtils.isNotBlank(prod.getIsScm())) {
			this.isScm = prod.getIsScm();
		}
		if (StringUtils.isNotBlank(prod.getSupplierId())) {
			this.supplierId = prod.getSupplierId();
		}
	}

	public CartOrderProduct addDetail(CartOrderProductDetail detail) {
		getDetails().add(detail);
		detail.setOrderProduct(this);
		detail.setCart(cart);
		detail.setDetailSeq(getDetails().size());
		detail.setProdSeq(getProdSeq());
		return this;
	}

	/**
	 * @return
	 * @deprecated use getTotalPrice()
	 */
	@Deprecated
	public BigDecimal getAmount() {
		return getTotalPrice();
	}

	/**
	 * @param amount
	 * @deprecated 由 details 計算, 不允許自行設定
	 */
	@Deprecated
	public void setAmount(BigDecimal amount) {
	}

	/**
	 * @return the applyCampaign
	 */
	public List<ApplyCampaign> getApplyCampaign() {
		if (applyCampaign == null) {
			applyCampaign = new ArrayList();
		}
		return applyCampaign;
	}

	/**
	 * @param applyCampaign the applyCampaign to set
	 */
	public void setApplyCampaign(List<ApplyCampaign> applyCampaign) {
		this.applyCampaign = applyCampaign;
	}

	/**
	 * @return the details
	 */
	public List<CartOrderProductDetail> getDetails() {
		if (details == null) {
			details = new ArrayList();
		}
		return details;
	}

	public BigDecimal getTotalPrice() {
		totalPrice = BigDecimal.ZERO;
		for (CartOrderProductDetail copd : getDetails()) {
			totalPrice = totalPrice.add(copd.getAmount().multiply(BigDecimal.valueOf(copd.getQty())));
		}
		return totalPrice;
	}

	/**
	 * @param totalPrice the totalPrice to set
	 * @deprecated 計算結果, 不需要 update
	 */
	@Deprecated
	public void setTotalPrice(BigDecimal totalPrice) {
	}

	/**
	 * @return the cartOrderProdId
	 */
	public Long getCartOrderProdId() {
		return cartOrderProdId;
	}

	/**
	 * @param cartOrderProdId the cartOrderProdId to set
	 */
	public void setCartOrderProdId(Long cartOrderProdId) {
		this.cartOrderProdId = cartOrderProdId;
	}

	/**
	 * @return the cartId
	 */
	public String getCartId() {
		return cartId;
	}

	/**
	 * @param cartId the cartId to set
	 */
	public void setCartId(String cartId) {
		this.cartId = cartId;
	}

	/**
	 * @return the cart
	 */
	public CartOrders getCart() {
		return cart;
	}

	/**
	 * @param cartOrder the cartOrder to set
	 */
	public void setCart(CartOrders cart) {
		this.cart = cart;
	}

	/**
	 * @return the prodSeq
	 */

	public int getProdSeq() {
		if (prodSeq == 0) {
			prodSeq = cart.getCartOrderProducts().indexOf(this) + 1;
		}
		return prodSeq;
	}

	/**
	 * @param prodSeq the prodSeq to set
	 * @deprecated 計算結果, 不需要 update
	 */
	@Deprecated
	public void setProdSeq(int prodSeq) {
		this.prodSeq = prodSeq;
	}

	/**
	 * @return the prodId
	 */
	public String getProdId() {
		return prodId;
	}

	/**
	 * @param prodId the prodId to set
	 */
	public void setProdId(String prodId) {
		this.prodId = prodId;
	}

	/**
	 * @return the prodSpecId
	 */
	public String getProdSpecId() {
		return prodSpecId;
	}

	/**
	 * @param prodSpecId the prodSpecId to set
	 */
	public void setProdSpecId(String prodSpecId) {
		this.prodSpecId = prodSpecId;
	}

	/**
	 * @return the prodName
	 */
	public String getProdName() {
		return prodName;
	}

	/**
	 * @param prodName the prodName to set
	 */
	public void setProdName(String prodName) {
		this.prodName = prodName;
	}

	/**
	 * @return the prodSpecName
	 */
	public String getProdSpecName() {
		return prodSpecName;
	}

	/**
	 * @param prodSpecName the prodSpecName to set
	 */
	public void setProdSpecName(String prodSpecName) {
		this.prodSpecName = prodSpecName;
	}

	/**
	 * @return the prodTp
	 */
	public String getProdTp() {
		return prodTp;
	}

	/**
	 * @param prodTp the prodTp to set
	 */
	public void setProdTp(String prodTp) {
		this.prodTp = prodTp;
	}

	/**
	 * @return the logisticTp
	 */
	public String getLogisticTp() {
		return logisticTp;
	}

	/**
	 * @param logisticTp the logisticTp to set
	 */
	public void setLogisticTp(String logisticTp) {
		this.logisticTp = logisticTp;
	}

	/**
	 * @return the logisticSendDt
	 */
	public Date getLogisticSendDt() {
		return logisticSendDt;
	}

	/**
	 * @param logisticSendDt the logisticSendDt to set
	 */
	public void setLogisticSendDt(Date logisticSendDt) {
		this.logisticSendDt = logisticSendDt;
	}

	/**
	 * @return the logisticFinalDt
	 */
	public Date getLogisticFinalDt() {
		return logisticFinalDt;
	}

	/**
	 * @param logisticFinalDt the logisticFinalDt to set
	 */
	public void setLogisticFinalDt(Date logisticFinalDt) {
		this.logisticFinalDt = logisticFinalDt;
	}

	/**
	 * @return the logisticSt
	 */
	public String getLogisticSt() {
		return logisticSt;
	}

	/**
	 * @param logisticSt the logisticSt to set
	 */
	public void setLogisticSt(String logisticSt) {
		this.logisticSt = logisticSt;
	}

	/**
	 * @return the logisticNo
	 */
	public String getLogisticNo() {
		return logisticNo;
	}

	/**
	 * @param logisticNo the logisticNo to set
	 */
	public void setLogisticNo(String logisticNo) {
		this.logisticNo = logisticNo;
	}

	/**
	 * @return the logisticCompany
	 */
	public String getLogisticCompany() {
		return logisticCompany;
	}

	/**
	 * @param logisticCompany the logisticCompany to set
	 */
	public void setLogisticCompany(String logisticCompany) {
		this.logisticCompany = logisticCompany;
	}

	/**
	 * @return the ecCost
	 */
	public BigDecimal getEcCost() {
		return ecCost;
	}

	/**
	 * @param ecCost the ecCost to set
	 */
	public void setEcCost(BigDecimal ecCost) {
		this.ecCost = ecCost;
	}

	/**
	 * @return the erpCost
	 */
	public BigDecimal getErpCost() {
		return erpCost;
	}

	/**
	 * @param erpCost the erpCost to set
	 */
	public void setErpCost(BigDecimal erpCost) {
		this.erpCost = erpCost;
	}

	/**
	 * @return the unitPrice
	 */
	public BigDecimal getUnitPrice() {
		return unitPrice;
	}

	/**
	 * @param unitPrice the unitPrice to set
	 */
	public void setUnitPrice(BigDecimal unitPrice) {
		this.unitPrice = unitPrice;
	}

	/**
	 * @return the qty
	 */
	public int getQty() {
		return qty;
	}

	/**
	 * @param qty the qty to set
	 */
	public void setQty(int qty) {
		this.qty = qty;
	}

	/**
	 * @return the discount
	 */
	public BigDecimal getDiscount() {
		return discount;
	}

	/**
	 * @param discount the discount to set
	 */
	public void setDiscount(BigDecimal discount) {
		this.discount = discount;
	}

	// /**
	// * @return the coupon
	// */
	// public BigDecimal getCoupon() {
	// return coupon;
	// }
	//
	// /**
	// * @param coupon the coupon to set
	// */
	// public void setCoupon(BigDecimal coupon) {
	// this.coupon = coupon;
	// }
	//
	// /**
	// * @return the couponId
	// */
	// public String getCouponId() {
	// return couponId;
	// }
	//
	// /**
	// * @param couponId the couponId to set
	// */
	// public void setCouponId(String couponId) {
	// this.couponId = couponId;
	// }

	/**
	 * @return the categoryPath
	 */
	public String getCategoryPath() {
		return categoryPath;
	}

	/**
	 * @param categoryPath the categoryPath to set
	 */
	public void setCategoryPath(String categoryPath) {
		this.categoryPath = categoryPath;
	}

	@Transient
	public String getCategoryId() {
		String cId = null;
		if (StringUtils.isNotBlank(categoryPath)) {
			String[] cIds = StringUtils.split(categoryPath, "/");
			cId = cIds[cIds.length - 1];
		}
		return cId;
	}

	/**
	 * @return the pmId
	 */
	public String getPmId() {
		return pmId;
	}

	/**
	 * @param pmId the pmId to set
	 */
	public void setPmId(String pmId) {
		this.pmId = pmId;
	}

	/**
	 * @return the pmGroup
	 */
	public String getPmGroup() {
		return pmGroup;
	}

	/**
	 * @param pmGroup the pmGroup to set
	 */
	public void setPmGroup(String pmGroup) {
		this.pmGroup = pmGroup;
	}

	/**
	 * @return the isCampaign
	 */
	public boolean isCampaign() {
		return isCampaign;
	}

	/**
	 * @param isCampaign the isCampaign to set
	 */
	public void setCampaign(boolean isCampaign) {
		this.isCampaign = isCampaign;
	}

	/**
	 * @return the isReturn
	 */
	public boolean isReturn() {
		return isReturn;
	}

	/**
	 * @param isReturn the isReturn to set
	 */
	public void setReturn(boolean isReturn) {
		this.isReturn = isReturn;
	}

	/**
	 * @return the isChange
	 */
	public boolean isChange() {
		return isChange;
	}

	/**
	 * @param isChange the isChange to set
	 */
	public void setChange(boolean isChange) {
		this.isChange = isChange;
	}

	/**
	 * @return the campaignId
	 */
	public String getCampaignId() {
		return campaignId;
	}

	/**
	 * @param campaignId the campaignId to set
	 */
	public void setCampaignId(String campaignId) {
		this.campaignId = campaignId;
	}

	/**
	 * @return the campaignName
	 */
	public String getCampaignName() {
		return campaignName;
	}

	/**
	 * @param campaignName the campaignName to set
	 */
	public void setCampaignName(String campaignName) {
		this.campaignName = campaignName;
	}

	/**
	 * @param details the details to set
	 */
	public void setDetails(List<CartOrderProductDetail> details) {
		this.details = details;
	}

	/**
	 * @return the isScm
	 */
	public String getIsScm() {
		return isScm;
	}

	/**
	 * @param isScm the isScm to set
	 */
	public void setIsScm(String isScm) {
		this.isScm = isScm;
	}

	/**
	 * @return the supplierId
	 */
	public String getSupplierId() {
		return supplierId;
	}

	/**
	 * @param supplierId the supplierId to set
	 */
	public void setSupplierId(String supplierId) {
		this.supplierId = supplierId;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "CartOrderProduct [cartId=" + cartId + ", prodId=" + prodId + ", prodSpecId=" + prodSpecId + ", prodTp="
				+ prodTp + ", unitPrice=" + unitPrice + ", qty=" + qty + ", totalPrice=" + totalPrice + ", discount="
				+ discount + ", applyCampaign=" + applyCampaign + "]";
	}

}
